/**
 * 
 */
package it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Date;
import java.util.Scanner;

import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.ai.AI;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.ai.decisiontreeai.DecisionTreeAI;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.filehandlers.CBVMap;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.filehandlers.ConcreteStartingRoleFactory;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.filehandlers.PlayerFileHandler;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.pawn.stats.StatsFactory;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.player.BattlePlayer;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.player.SimplePlayer;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.world.Map;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.component.world.MapManager;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.EventListener;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.events.GenericEvent;
import it.unical.canonaco.rende.igpe.game.cbv.logiclayer.engine.exceptions.InvalidFileException;

/**
 * @author Massimo Canonaco
 *
 */
public class GameManager implements EventListener
{
	/**It's the path for the file which contains all the settings for the GameManager*/
	static private final String SETTINGS_FILE = "cbvapps"+File.separatorChar+"gmconfig.cfg";
	
	/**It's the current player profile on this 'machine' */
	private SimplePlayer clientPlayer;
	
	/**It's the current "battle side" of the current player on this 'machine' */
	private BattlePlayer battleClientPlayer;
	
	/**It's the manager of the maps, for getting the actual or the next map. */
	private MapManager mapManager;
	
	/**It's the manager for the match when two players are playing against. */
	private MatchManager matchManager;
	
	/**It's the factory for getting the roles statics of the characters. */
	private StatsFactory statsFactory;
	
	/**It loads and save the profile of the current player (clientPlayer). */
	private PlayerFileHandler profileLoader;
	
	/**It's artificial intelligence for single player games. */
	private AI ai;
	
	/**
	 * @throws IOException  */
	public GameManager() throws IOException
	{
		// It contains all the configuration informations of the managers and parts of the GameManager.
		SettingsBean settings = new SettingsBean();
		
		// Load the settings informations.
		loadSettings(settings);
		
		// Initialize the statics factory.
		statsFactory = new StatsFactory(new ConcreteStartingRoleFactory(), settings.getRolesFolder());
		
		// Initialize the match manager.
		matchManager = new MatchManager(settings.getStartingSkillPoints(),
										settings.getUpdateSkillPoints(),
										settings.getMaxBattleCharacters(),
										statsFactory);
		
		clientPlayer = new SimplePlayer();
		battleClientPlayer = new BattlePlayer();
		mapManager = new MapManager(new CBVMap(), settings.getMapsFolder());
		mapManager.init(settings.getMapManagerConfigFile());
		profileLoader = new PlayerFileHandler(settings);
		ai = new DecisionTreeAI(statsFactory, battleClientPlayer);
		Thread aiThread = new Thread(ai);
		aiThread.start();
	}
	
	/** */
	public void reset()
	{
		clientPlayer = new SimplePlayer();
		battleClientPlayer = new BattlePlayer();
	}
	/**
	 * @throws IOException */
	private void loadSettings(SettingsBean settings) throws IOException
	{
		BufferedReader fileReader = new BufferedReader(new FileReader(GameManager.SETTINGS_FILE));
		final char  customSeparatorChar = '+';
		final String texturesTag = "textures",
					 rolesTag = "roles",
					 mapsTag = "maps",
					 mapsCicleTag = "mapsCicle",
					 startSPtag = "startSP",
					 updateSPtag = "updateSP",
					 profilesTag = "profiles",
					 itemsTag = "items",
					 commentTag = "#",
					dDot = ":";
		String rLine = null;
		try{
			while((rLine = fileReader.readLine()) != null)
			{
//				System.out.println("letto --->"+rLine);
				if(rLine.startsWith(commentTag)) // Comment
				{
					//It's a comment, do nothing.
				}
				else if(rLine.startsWith(profilesTag)) // Profiles
				{
					settings.setProfilesFolder(rLine.substring(rLine.indexOf(dDot) + 1).replace(customSeparatorChar, File.separatorChar));
				}
				else if(rLine.startsWith(mapsCicleTag)) // Maps cicle file
				{
					settings.setMapManagerConfigFile(rLine.substring(rLine.indexOf(dDot) + 1).replace(customSeparatorChar, File.separatorChar));
				}
				else if(rLine.startsWith(mapsTag)) // Maps
				{
					settings.setMapsFolder(rLine.substring(rLine.indexOf(dDot) + 1).replace(customSeparatorChar, File.separatorChar));
				}
				else if(rLine.startsWith(rolesTag)) // Roles
				{
					settings.setRolesFolder(rLine.substring(rLine.indexOf(dDot) + 1).replace(customSeparatorChar, File.separatorChar));
				}
				else if(rLine.startsWith(texturesTag)) // Textures
				{
					settings.setTexturesFolder(rLine.substring(rLine.indexOf(dDot) + 1).replace(customSeparatorChar, File.separatorChar));
				}
				else if(rLine.startsWith(startSPtag)) // Starting Skill Points
				{
					settings.setStartingSkillPoints(Integer.parseInt(rLine.substring(rLine.indexOf(dDot) + 1)));
				}
				else if(rLine.startsWith(updateSPtag)) // Updating Skill Points
				{
					settings.setUpdateSkillPoints(Integer.parseInt(rLine.substring(rLine.indexOf(dDot) + 1)));
				}
				else if(rLine.startsWith(itemsTag)) // Items
				{
					settings.setItemsFile(rLine.substring(rLine.indexOf(dDot) + 1).replace(customSeparatorChar, File.separatorChar));
				}
			}
		}
		finally
		{
			fileReader.close();
		}
	}
	
	/** */
	// test
//	public void newGame() throws FileNotFoundException, IOException, InvalidFileException 
//	{
//		Map arena = mapManager.nextMap();
//		
//		if(arena != null)
//		{
//			SimplePlayer playerTwo = new SimplePlayer();
//			BattlePlayer one = new BattlePlayer();
//			one.setNickname(clientPlayer.getNickname());
//			matchManager.init(clientPlayer, playerTwo, one, null, arena,statsFactory);
//		}
//		
////		battleClientPlayer.setNickname(clie);
//	}
	
	@Override
	public void notify(GenericEvent event) 
	{
		// TODO: fare questo metodo 
	}

	/**
	 * @return the profileLoader
	 */
	public PlayerFileHandler getProfileLoader() {
		return profileLoader;
	}

	/**
	 * @return the clientPlayer
	 */
	public SimplePlayer getClientPlayer() {
		return clientPlayer;
	}

	/**
	 * @return the mapManager
	 */
	public MapManager getMapManager() {
		return mapManager;
	}

	/**
	 * @return the matchManager
	 */
	public MatchManager getMatchManager() 
	{
		return matchManager;
	}

	/**
	 * @return the statsFactory
	 */
	public StatsFactory getStatsFactory() 
	{
		return statsFactory;
	}
	
	/** */
	public BattlePlayer getClientBattlePlayer()
	{
		return battleClientPlayer;
	}

	/**
	 * @return the ai
	 */
	public AI getAi() {
		return ai;
	}

	/**
	 * @param ai the ai to set
	 */
	public void setAi(AI ai) {
		this.ai = ai;
	}
}
